Bar plot

library(datasets)
library(dplyr)
data(mtcars)
head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
glimpse(mtcars)
Observations: 32
Variables: 11
$ mpg  <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8…
$ cyl  <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8…
$ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 1…
$ hp   <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 18…
$ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92…
$ wt   <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3…
$ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 1…
$ vs   <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0…
$ am   <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0…
$ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3…
$ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2…
#select mpg and cylinder
mt_sel<-select(mtcars,mpg:cyl)
head(mt_sel)
                   mpg cyl
Mazda RX4         21.0   6
Mazda RX4 Wag     21.0   6
Datsun 710        22.8   4
Hornet 4 Drive    21.4   6
Hornet Sportabout 18.7   8
Valiant           18.1   6
#convert cyl to a factor variable
cyl<-as.factor(mtcars$cyl)
class(cyl)
[1] "factor"
levels(cyl)
[1] "4" "6" "8"
#sum using tapply
mt_sum<-tapply(mtcars$mpg,mtcars$cyl,sum)
mt_sum
    4     6     8 
293.3 138.2 211.4 
#plot the graph
mt_plot<-barplot(mt_sum,xlab="Cylinder",ylab="Total MPG",names.arg=c("Four","Six","Eight"),
ylim=c(0,350),col=c("red","green","yellow"),main="Barplot of Cylinder and corresponding MPG Total",las=1)
#add data labels
text(mt_plot,mt_sum,label=mt_sum,pos=3)
#add legend
legend("topright",legend=c("Four","Six","Eight"),fill=c("red","green","yellow"),bty="n",pch=20,
       cex=1)

Barplot using Frequency or Count

library(datasets)
data(mtcars)
#create table using the factor variable
cyl<-as.factor(mtcars$cyl)
mt_count<-table(mtcars$cyl)
mt_count

 4  6  8 
11  7 14 
#barplot
mt_plot<-barplot(mt_count,xlab="Cylinder",ylab="Frequency",las=1,col=c("maroon","pink","blue"), main="Barplot of Cylinder",ylim=c(0,20),names.arg=c("Four","Six","Eight"))
#add data labels
text(mt_plot,mt_count,label=mt_count,pos=3)
#add legend
legend("top",legend=c("Four","Six","Eight"),fill=c("maroon","pink","blue"),bty="n",pch=20,
       cex=1.2,horiz=TRUE)

Barplot-Relative Frequency(%)

library(datasets)
data(mtcars)
#create table using the factor variable
cyl<-as.factor(mtcars$cyl)
percent<-table(mtcars$cyl)/32
mt_plot<-barplot(percent,xlab="Cylinder",ylab="Relative Freq.",col=c("purple","orange","red"),
main="Relative Frequency Barplot",names.arg=c("Four","Six","Eight"),las=1,ylim=c(0,0.5))
#add data labels
text(mt_plot,percent,label=percent,pos=3)

Barplot-Percentage(%)

library(datasets)
data(mtcars)
#create table using the factor variable
cyl<-as.factor(mtcars$cyl)
percent<-table(mtcars$cyl)/32
mt_plot<-barplot(percent,xlab="Cylinder",ylab="Percent(%)",col=c("purple","orange","red"),
main="Percentage Barplot",names.arg=c("Four","Six","Eight"),las=1,ylim=c(0,0.5))
#add data labels
text(mt_plot,percent,label=c("34%","22%","44%"),pos=3)

ggplot2 graphics

Basic Bar Chart

library(ggplot2)
library(gridExtra)
library(plotly)
library(datasets)
data(mtcars)
head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
p1<-ggplot(mtcars,aes(x=cyl,fill=cyl))+geom_bar()+ggtitle("Fig.A:x-axis as a continuous variable")
ggplotly(p1)
p2<-ggplot(mtcars,aes(x=factor(cyl),fill=factor(cyl)))+geom_bar()+ggtitle("Fig.B:x-axis as a categorical(factor) variable")
ggplotly(p2)
grid.arrange(p1,p2,ncol=2)

  • An alternative use of a bar chart is to plot a second variable on the y-axis to compare the x-axis categories across. For instance, we may want to assess the average mpg that 4, 6, and 8 cylinder cars get. We include the argument stat = “identity” in geom_bar() which tells R to use the y values for the height of the bars.
library(dplyr)

cyl_mpg <- mtcars %>%
        group_by(cyl) %>%
        summarise(avg_mpg = mean(mpg, na.rm = TRUE))

g<-ggplot(cyl_mpg, aes(x = factor(cyl), y = avg_mpg,fill=factor(cyl))) +
        geom_bar(stat = "identity")
ggplotly(g)
  • Although the default width of the bars is aesthetically pleasing, you do have the ability to adjust this attribute by setting the width in geom_bar(). The default width is 0.9; smaller values make the bars narrower and larger values (max width of 1) make the bars wider.

Adjust width of bars

p1 <- ggplot(mtcars, aes(x = factor(cyl),fill=factor(cyl))) +
        geom_bar(width = .5) +
        ggtitle("bar width = 0.5")
        

p2 <- ggplot(mtcars, aes(x = factor(cyl),fill=factor(cyl))) +
        geom_bar(width = .75) +
        ggtitle("bar width = 0.75")

p3 <- ggplot(mtcars, aes(x = factor(cyl),fill=factor(cyl))) +
        geom_bar(width = .9) +
        ggtitle("bar width = 0.9")

p4 <- ggplot(mtcars, aes(x = factor(cyl),fill=factor(cyl))) +
        geom_bar(width = .99) +
        ggtitle("bar width = 0.99")

grid.arrange(p1, p2, p3, p4, ncol = 2,nrow=2)

g<-ggplot(mtcars, aes(x = factor(cyl))) +
        geom_bar(fill = "royalblue", color = "red", alpha = .8)
ggplotly(g)

Rotate text along the x-axis using theme()

p1 <- ggplot(mtcars, aes(x = row.names(mtcars), y = mpg)) +
        geom_bar(stat = "identity") +
        ggtitle("Fig. A: Default x-axis")

p2 <- ggplot(mtcars, aes(x = row.names(mtcars), y = mpg)) +
        geom_bar(stat = "identity") +
        theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5)) +
        ggtitle("Fig. B: Rotated x-axis")

grid.arrange(p1, p2, ncol = 1)

Apply coord_flip() to rotate the axes

# rotate to make more readable
p1 <- ggplot(mtcars, aes(x = row.names(mtcars), mpg)) +
        geom_bar(stat = "identity") +
        coord_flip() +
        ggtitle("Fig. A: Default rotated x-axis")

# order bars
p2 <- ggplot(mtcars, aes(x = reorder(row.names(mtcars), mpg), y = mpg)) +
        geom_bar(stat = "identity") +
        coord_flip() +
        ggtitle("Fig. B: Rotated ordered x-axis")

grid.arrange(p1, p2, ncol = 2)

Comparing Groups

# compare mpg across all cars and color based on cyl
p1 <- ggplot(mtcars, aes(x = reorder(row.names(mtcars), mpg), y = mpg, fill = factor(cyl))) +
        geom_bar(stat = "identity") +
        coord_flip() +
        theme_minimal() +
        ggtitle("Fig. A: Default fill colors")

p2 <- ggplot(mtcars, aes(x = reorder(row.names(mtcars), mpg), y = mpg, fill = factor(cyl))) +
        scale_fill_manual(values = c("#e5f5e0", "#a1d99b", "#31a354")) +
        geom_bar(stat = "identity") +
        coord_flip() +
        theme_minimal() +
        ggtitle("Fig. B: Manually set fill colors")

grid.arrange(p1, p2, ncol = 2)

Group Bar Graph

library(dplyr)
avg_mpg <- mtcars %>%
        group_by(cyl, am) %>%
        summarise(mpg = mean(mpg, na.rm = TRUE))

avg_mpg
# A tibble: 6 x 3
# Groups:   cyl [3]
    cyl    am   mpg
  <dbl> <dbl> <dbl>
1     4     0  22.9
2     4     1  28.1
3     6     0  19.1
4     6     1  20.6
5     8     0  15.0
6     8     1  15.4
p1 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity", position = "dodge") +
        ggtitle("Default color comparison")

# more pleasing colors
p2 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity", position = "dodge", color = "grey40") +
        scale_fill_brewer(palette = "Pastel1") +
        ggtitle("Adjusted color comparison")

grid.arrange(p1, p2, ncol = 2)

Adjust the dodge width in geom_bar()

p1 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity", position = "dodge") +
        ggtitle("Default dodge positioning") +
        theme(legend.position = "none")

p2 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity", position = position_dodge(width = .5)) +
        ggtitle("Overlap of side-by-side bars") +
        theme(legend.position = "none")

p3 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity", position = position_dodge(width = 1)) +
        ggtitle("Spacing between side-by-side bars") +
        labs(fill = "AM") +
        theme(legend.position = c(1,1), legend.justification = c(1,1),
              legend.background = element_blank())

grid.arrange(p1, p2, p3, ncol = 3)

Stacked Bar Graph

g<-ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity")
ggplotly(g)
# Reverse legend color coding layout
p1 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity") +
        guides(fill = guide_legend(reverse = TRUE)) +
        labs(fill = "am") +
        ggtitle("Fig A: Reverse legend")

# or reverse stacking order by changing the factor levels
p2 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am, levels = c(1, 0)))) +
        geom_bar(stat = "identity") +
        labs(fill = "am") +
        ggtitle("Fig B: Specify levels")

grid.arrange(p1, p2, ncol = 2)

Change the color of stacked bars

g<-ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am, levels = c(1, 0)))) +
        geom_bar(stat = "identity", color = "grey40") +
        scale_fill_manual(values = c("#a1d99b", "#31a354")) +
        labs(fill = "AM")
ggplotly(g)

Proportional Stacked Bars

library(datasets)
library(ggplot2)
library(plotly)
library(dplyr)
library(plyr)
# calculate percentages of each cyl & am category
proportion <- mtcars %>%
        group_by(cyl, am) %>%
        tally() %>%
        group_by(cyl) %>%
        mutate(pct = n / sum(n))

proportion
# A tibble: 6 x 4
# Groups:   cyl [3]
    cyl    am     n    pct
  <dbl> <dbl> <int>  <dbl>
1     4     0     3 0.0938
2     4     1     8 0.25  
3     6     0     4 0.125 
4     6     1     3 0.0938
5     8     0    12 0.375 
6     8     1     2 0.0625
# create proportional stacked bars
g<-ggplot(proportion, aes(factor(cyl), pct, fill = factor(am, levels = c(1, 0)))) +
        geom_bar(stat = "identity", color = "grey40") +
        scale_fill_manual(values = c("#a1d99b", "#31a354")) +
        labs(fill = "AM")
ggplotly(g)

Add Value Markers

Add Labels on Bars

p1 <- ggplot(mtcars, aes(reorder(row.names(mtcars), mpg), mpg)) +
        geom_bar(stat = "identity") +
        coord_flip() +
        geom_text(aes(label = mpg), nudge_y = 2)

p2 <- ggplot(mtcars, aes(reorder(row.names(mtcars), mpg), mpg)) +
        geom_bar(stat = "identity") +
        coord_flip() +
        geom_text(aes(label = mpg), nudge_y = -2, color = "white")

grid.arrange(p1, p2, ncol = 2)

  • If you want to draw attention to one specific bar you can create a new TRUE/FALSE variable that marks the specific vehicle of interest. In the following case I also add the Make of the car as a variable since the mtcars only uses the make as a row name, which can be erased when making changes to the data frame. You can then fill by the new ID variable in the first line of code and use annotate() to specify the exact text you want to highlight for that bar.

Draw attention to one specific bar

cars <- mtcars %>%
        mutate(Make = row.names(mtcars),
               ID = ifelse(Make == "Fiat X1-9", TRUE, FALSE))

ggplot(cars, aes(reorder(Make, mpg), mpg, fill = ID)) +
        geom_bar(stat = "identity") +
        coord_flip() +
        scale_fill_manual(values = c("grey90", "dodgerblue")) +
        annotate("text", x = "Fiat X1-9", y = 22, label = "mpg = 27.3", color = "white") +
        theme_minimal() +
        theme(legend.position = "none")

labeling grouped bar graph

p1 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity", position = "dodge") +
        geom_text(aes(label = round(mpg, 1)), position = position_dodge(0.9),vjust=-0.5) +
        ggtitle("Fig A: Default text alignment")

p2 <- ggplot(avg_mpg, aes(factor(cyl), mpg, fill = factor(am))) +
        geom_bar(stat = "identity", position = "dodge") +
        geom_text(aes(label = round(mpg, 1)), position = position_dodge(0.9),
                  vjust = 1.5, color = "white") +
        ggtitle("Fig B: Adjusted text alignment")

grid.arrange(p1, p2, ncol = 2)

Add labels to proportional bar graphs

# create label location for each proportional bar
proportion <- proportion %>%
        group_by(cyl) %>%
        mutate(label_y = cumsum(pct))

ggplot(proportion, aes(factor(cyl), pct, fill = factor(am, levels = c(1, 0)))) +
        geom_bar(stat = "identity", color = "black") +
        geom_text(aes(label = round(pct, 2), y = label_y), vjust = 1.5, color = "white") +
        scale_fill_manual(values = c("red", "blue")) +
        labs(fill = "AM")

Barplots,Piechart,Density Plots and Histogram

Use billboarder and breakDown packages

library(billboarder)
library(breakDown)
library(datasets)
data(mtcars)
str(mtcars)
'data.frame':   32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
cyl<-as.factor(mtcars$cyl)
cyl<-table(mtcars$cyl)

billboarder()%>%
        bb_barchart(cyl)

Horizontal Bars

library(billboarder)
library(breakDown)
library(datasets)
data(mtcars)
str(mtcars)
'data.frame':   32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
cyl<-as.factor(mtcars$cyl)
cyl<-table(mtcars$cyl)

billboarder()%>%
        bb_barchart(cyl,rotated=TRUE)

Barchat continued

library(billboarder)
library(breakDown)
library(datasets)
data(mtcars)

am<-as.factor(mtcars$am)
am<-table(mtcars$am)

billboarder()%>%
        bb_barchart(am)

Histogram using the billboarder package

library(billboarder)
library(breakDown)
library(datasets)
data(mtcars)

mpg<-mtcars$mpg #use continuous data for histograms

billboarder()%>%
        bb_histogram(mpg)
#lets use wt which is continuos
wt<-mtcars$wt
billboarder()%>%
        bb_histogram(wt)
#introduce group
cyl<-as.factor(mtcars$cyl)

billboarder()%>%
        bb_histogram(mpg,group=cyl)

Density plot using billboarder package

library(billboarder)
library(breakDown)
library(datasets)
data(mtcars)

#first density plot
cyl<-as.factor(mtcars$cyl)

billboarder()%>%
        bb_densityplot(mpg,group=cyl)
#second density plot
gear<-as.factor(mtcars$gear)
billboarder()%>%
        bb_densityplot(mpg,group=gear)
#third density plot
hp<-mtcars$hp
vs<-as.factor(mtcars$vs)

billboarder()%>%
        bb_densityplot(hp,group=vs)

Pie Chart using the billboarder package

library(billboarder)
library(breakDown)
library(dplyr)
library(datasets)
data(mtcars)

#first pie chart
cyl<-as.factor(mtcars$cyl)
cyl<-table(mtcars$cyl)

billboarder()%>%
        bb_piechart(cyl)
#second pie chart
gear<-table(mtcars$gear)

billboarder()%>%
        bb_piechart(gear)
#third pie chart
mpg<-as.factor(mtcars$mpg)
mpg<-table(mtcars$mpg)

billboarder()%>%
        bb_piechart(mpg)

Lollipop Chart with Conditional Color

library(dplyr)
library(ggplot2)
library(plotly)
x<-seq(0,2*pi,length.out=100)
data<-data.frame(x=x,y=sin(x)+rnorm(100,sd=0.2))
#add a column with your condition for the color

data<-data %>%
        mutate(mycolor=ifelse(y>0,"type1","type2"))

#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=0,yend=y,color=mycolor,size=1.3,alpha=0.9))+theme_light()+theme(legend.position="none",panel.border=element_blank())+xlab("")+ylab("value of Y")
ggplotly(g)

Lollipop considering a dataset

library(dplyr)
library(ggplot2)
library(plotly)
library(datasets)
data(mtcars)
data<-select(mtcars,mpg,hp)
x<-mtcars$hp
y<-mtcars$mpg
mny<-mean(y)
data<-data %>%
        mutate(mycolor=ifelse(y>mny,"type1","type2"))
#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=mny,yend=y,color=mycolor,size=1.2,alpha=0.9))+theme_light()+theme(legend.position="none",panel.border=element_blank())+xlab("")+ylab("value of Y")
ggplotly(g)

Custom Lollipop Chart

  1. A marker

  2. A stem

library(tidyverse)
#create data
data<-data.frame(x=LETTERS[1:26],y=abs(rnorm(26)))

#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=0,yend=y))+geom_point(size=5,color="red",
        fill=alpha("orange",0.3),alpha=0.7,shape=21,stroke=2)
ggplotly(g)

Custom Lollipop chart considering a dataset

library(tidyverse)
library(dplyr)
library(ggplot2)
library(plotly)
library(datasets)
data(mtcars)
data<-select(mtcars,mpg,hp)
x<-mtcars$hp
y<-mtcars$mpg

#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=0,yend=y))+geom_point(size=5,color="red",
        fill=alpha("orange",0.3),alpha=0.7,shape=21,stroke=2)+xlab("HP")+ylab("MPG")+ggtitle("Custom Lollipop of HP and MPG")
ggplotly(g)

Custom Lollipop with conditional color

library(tidyverse)
library(dplyr)
library(ggplot2)
library(plotly)
library(datasets)
data(mtcars)
data<-select(mtcars,mpg,hp)
x<-mtcars$hp
y<-mtcars$mpg
mny<-mean(y)
data<-data %>%
        mutate(mycolor=ifelse(y>mny,"type1","type2"))
#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=mny,yend=y,color=mycolor))+geom_point(size=5,color="red",fill=alpha("orange",0.5),alpha=0.7,shape=21,stroke=2)+xlab("HP")+ylab("MPG")+ggtitle("Custom Lollipop of HP and MPG with conditional color")
ggplotly(g)

Stem Chart

library(tidyverse)
library(ggplot2)
library(plotly)
#create data
data<-data.frame(x=LETTERS[1:26],y=abs(rnorm(26)))

#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=0,yend=y),size=1,color="blue",
linetype="dotdash")+geom_point(size=4,color="red",
fill=alpha("orange",0.9),alpha=0.7,shape=20,stroke=2)
ggplotly(g)

Stem Chart considering a dataset

library(tidyverse)
library(dplyr)
library(ggplot2)
library(plotly)
library(datasets)
data(mtcars)
data<-select(mtcars,mpg,hp)
x<-mtcars$hp
y<-mtcars$mpg

#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=0,yend=y),size=1,color="blue",
linetype="dotdash")+geom_point(size=5,color="red",
fill=alpha("orange",0.3),alpha=0.7,shape=20,stroke=2)+xlab("HP")+ylab("MPG")+ggtitle("Custom Stem of HP and MPG")
ggplotly(g)

Custom Stem Chart with conditional color

library(tidyverse)
library(dplyr)
library(ggplot2)
library(plotly)
library(datasets)
data(mtcars)
data<-select(mtcars,mpg,hp)
x<-mtcars$hp
y<-mtcars$mpg
mny<-mean(y)
data<-data %>%
        mutate(mycolor=ifelse(y>mny,"type1","type2"))
#plot
g<-ggplot(data,aes(x=x,y=y))+geom_segment(aes(x=x,xend=x,y=mny,yend=y,color=mycolor),size=1,color="blue",linetype="dotdash")+geom_point(size=5,color="red",fill=alpha("orange",0.5),alpha=0.7,shape=20,stroke=2)+xlab("HP")+ylab("MPG")+ggtitle("Custom Stem Chart of HP and MPG with conditional color")
ggplotly(g)